package com.dongdongqiang.common.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工具类
 * Created by zzb on 15/12/30.
 */
public class Misc {
    public static boolean toBoolean(String s) {
        return "true".equals(StringUtils.trim(s)) || "1".equals(StringUtils.trim(s));
    }

    public static boolean isZero(Long i) {
        return i == null || i.equals(0L);
    }

    public static boolean isZero(Integer i) {
        return i == null || i.equals(0);
    }

    public static boolean isZero(Float f) {
        return f == null || f.equals(0f);
    }

    public static boolean isZero(Double d) {
        return d == null || d.equals(0d);
    }

    public static boolean isZero(BigDecimal d) {
        return d == null || d.compareTo(BigDecimal.ZERO) == 0;
    }

    public static boolean isNotZero(Integer i) {
        return !isZero(i);
    }

    public static boolean isNotZero(Float f) {
        return !isZero(f);
    }

    public static boolean isNotZero(Double d) {
        return !isZero(d);
    }

    public static boolean isNotZero(BigDecimal d) {
        return !isZero(d);
    }

    public static boolean isTrue(Boolean b) {
        return null != b && b;
    }

    public static boolean isFalse(Boolean b) {
        return !isTrue(b);
    }

    public static int toPrimitive(Integer value, int defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static float toPrimitive(Float value, float defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static double toPrimitive(Double value, double defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static char toPrimitive(Character value, char defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static boolean toPrimitive(Boolean value, boolean defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static short toPrimitive(Short value, short defaultValue) {
        return value == null ? defaultValue : value;
    }

    public static boolean isNumber(String str) {
        try {
            long l = Long.parseLong(str);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static boolean isNotNumber(String str) {
        return !isNumber(str);
    }

    public static int compare(BigDecimal d1, BigDecimal d2) {
        if (d1 == null) return -1;
        if (d2 == null) return 1;
        if (d1.doubleValue() == d2.doubleValue()) return 0;
        if (d1.doubleValue() > d2.doubleValue()) return 1;
        if (d1.doubleValue() < d2.doubleValue()) return -1;
        return 0;
    }

    static int index = 1;

    /**
     * 基于时间生成唯一表示，可以用来代替UUID，但同一毫秒不能超过999条
     */
    public static Long generateTimeKeyLong() {
        return Long.parseLong(generateTimeKey());
    }

    public static synchronized String generateTimeKey() {
        if (index == 999) {
            index = 1;
        }
        DecimalFormat df = new DecimalFormat("000");
        return DateTime.now().getMillis() + "" + df.format(index++);
    }

    /**
     * 获取随机字符串
     */
    public static String getRandomString(int length) { //length表示生成字符串的长度
        String base = "abcdefghijkmnpqrstuvwxyz23456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * 生成密码
     */
    public static String generatePassword(String password) {
        //如果长度为32位，说明已经加密过了
        if (StringUtils.length(password) != 32) {
            String originPassword;
            if (StringUtils.isNotBlank(password)) {
                originPassword = password;
            } else {
                //如果没有密码，默认为123456
                originPassword = "123456";
            }

            try {
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                byte[] bytes = md5.digest(originPassword.getBytes("utf-8"));
                password = bytesToString(bytes);
            } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        return password;
    }

    public static String bytesToString(byte[] bs) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bs) {
            // 第一步，将数据全部转换成正数：
            // 解释：为什么采用b&255
                             /*
                  * b:它本来是一个byte类型的数据(1个字节) 255：是一个int类型的数据(4个字节)
                  * byte类型的数据与int类型的数据进行运算，会自动类型提升为int类型 eg: b: 1001 1100(原始数据)
                  * 运算时： b: 0000 0000 0000 0000 0000 0000 1001 1100 255: 0000
                  * 0000 0000 0000 0000 0000 1111 1111 结果：0000 0000 0000 0000
                  * 0000 0000 1001 1100 此时的temp是一个int类型的整数
                  */
            int temp = b & 255;
            // 第二步，将所有的数据转换成16进制的形式
            // 注意：转换的时候注意if正数>=0&&<16，那么如果使用Integer.toHexString()，可能会造成缺少位数
            // 因此，需要对temp进行判断
            if (temp < 16 && temp >= 0) {
                // 手动补上一个“0”
                hexString.append("0").append(Integer.toHexString(temp));
            } else {
                hexString.append(Integer.toHexString(temp));
            }
        }
        return hexString.toString();
    }

    /**
     * 获取图片信息
     */
    public static Map<String, Integer> imageInfo(InputStream is) {
        Map<String, Integer> imageInfoMap = new HashMap<>();
        try {
            BufferedImage bufferedImage = ImageIO.read(is);
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            imageInfoMap.put("h", height);
            imageInfoMap.put("w", width);
        } catch (IOException e) {
            //TODO
            imageInfoMap.put("h", 500);
            imageInfoMap.put("w", 500);
        }
        return imageInfoMap;
    }

    /**
     * 判断是不是手机号码
     */
    public static boolean isMobilephone(String mobilephone) {
        if (StringUtils.isBlank(mobilephone)) return false;
        String reg = "^1(3[0-9]|4[0-9]|5[0-9]|7[0-9]|8[0-9])\\d{8}$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(mobilephone);
        return matcher.find();
    }

    /**
     * 是否是手机号或座机
     */
    public static boolean isPhone(String phone) {
        if (StringUtils.isBlank(phone)) return false;
        String reg = "^(0|86|17951)?(13[0-9]|15[0-9]|17[0-9]|18[0-9]|14[0-9])[0-9]{8}$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(phone);
        return matcher.find();

    }

    /**
     * 判断字符串是不是汉字
     */
    public static boolean isChinese(String str) {
        if (StringUtils.isBlank(str)) return false;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (!isChineseChar(c)) return false;
        }
        return true;
    }

    /**
     * 判断字符是不是汉字
     */
    public static boolean isChineseChar(char oneChar) {
        return (oneChar >= '\u4e00' && oneChar <= '\u9fa5')
                || (oneChar >= '\uf900' && oneChar <= '\ufa2d');
    }

    /**
     * 是否是身份证
     */
    public static boolean isIdCard(String idCard) {
        if (StringUtils.isBlank(idCard)) return false;
        String reg = "^((11|12|13|14|15|21|22|23|31|32|33|34|35|36|37|41|42|43|44|45|46|50|51|52|53|54|61|62|63|64|65|71|81|82|91)\\d{4})((((19|20)(([02468][048])|([13579][26]))0229))|((20[0-9][0-9])|(19[0-9][0-9]))((((0[1-9])|(1[0-2]))((0[1-9])|(1\\d)|(2[0-8])))|((((0[1,3-9])|(1[0-2]))(29|30))|(((0[13578])|(1[02]))31))))((\\d{3}(x|X))|(\\d{4}))$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(idCard);
        return matcher.find();
    }

    /**
     * 判断是否是澳门的身份证
     */
    public static boolean isAoMenIdCard(String idCard) {
        if (StringUtils.isBlank(idCard)) return false;
        String reg = "^[1|5|7][0-9]{6}\\([0-9Aa]\\)$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(idCard);
        return matcher.find();
    }

    /**
     * 判断是否是台湾的身份证
     */
    public static boolean isTaiWanIdCard(String idCard) {
        if (StringUtils.isBlank(idCard)) return false;
        String reg = "^[A-Z][0-9]{9}$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(idCard);
        return matcher.find();
    }

    /**
     * 判断是否是香港的身份证
     */
    public static boolean isXiangGangIdCard(String idCard) {
        if (StringUtils.isBlank(idCard)) return false;
        String reg = "^[A-Z][0-9]{6}\\([0-9A]\\)$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(idCard);
        return matcher.find();
    }


    /**
     * 获取当前域名
     */
    public static String getDomainName(HttpServletRequest request) {
        StringBuilder domainName = new StringBuilder();
        String serverName = request.getServerName();
        String scheme = request.getScheme();
        domainName.append(scheme).append("://").append(serverName);
        int serverPort = request.getServerPort();
        if (serverPort != 80) {
            domainName.append(":").append(serverPort);
        }
        return domainName.toString();
    }

    public static String toJSONString(Object o) {
        return JSON.toJSONString(o);
    }

    public static void main(String[] args) {
        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        DateTime dateTime = DateTime.parse("2016-10-29 22:00:00", format);
    }

    /**
     * 将一个列表更具某个属性分组
     */
    public static <T> Map<String, List<T>> parseToStringKeyMap(List<T> entities, String propertyName) throws Exception {
        final Map<String, List<T>> map = new HashMap<>();
        if (entities != null && entities.size() != 0)
            for (T t : entities) {
                Field field = ReflectionUtils.getAllDeclaredField(entities.get(0).getClass(), propertyName);
                if (!field.getType().equals(String.class)) throw new Exception("所选分类属性类型必须是String");
                Object propertyValue = FieldUtils.readDeclaredField(t, propertyName, true);
                if (propertyValue == null) continue;
                String propertyStringValue = (String) propertyValue;

                if (!map.containsKey(propertyStringValue)) {
                    map.put(propertyStringValue, new ArrayList<>());
                }

                map.get(propertyStringValue).add(t);
            }
        return map;
    }

}
